package org.dylan.common.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javacommon.xsqlbuilder.XsqlBuilder;
import javacommon.xsqlbuilder.XsqlBuilder.XsqlFilterResult;

import org.dylan.common.model.BaseQueryParam;
import org.dylan.common.model.OrderBy;
import org.dylan.common.model.QueryRequest;
import org.dylan.common.model.OrderBy.Direction;
import org.dylan.common.model.QueryParam;
import org.dylan.common.paging.PageRequest;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Restrictions;
import org.springframework.util.Assert;
/**
 * 
 * @author dylan
 * @date 2013-6-4 上午9:13:42
 */
public class XSqlUtils {
	
	public static final String SORT_COLUMNS_KEY = "_sort_columns";

	/**
	 * 从sql中移除select 子句，未考虑union的情况
	 * @param hql
	 * @return
	 */
    public static String removeSelect(String hql) {
        Assert.hasText(hql);
        int beginPos = hql.toLowerCase().indexOf("from");
        Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
        return hql.substring(beginPos);
    }

    /**
     * 从sql中移除order by 子句
     * @param hql
     * @return
     */
    public static String removeOrders(String hql) {
        Assert.hasText(hql);
        Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(hql);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return sb.toString();
    }
    /**
     * 从hql中移除 fetch关键字
     * @param hql
     * @return
     */
    public static String removeFetchKeyword(String hql) {
    	return hql.replaceAll("(?i)fetch", "");
    }
    /**
     * 从xsql语句中移除/~ order by ~/子句
     * @param string
     * @return
     */
	public static String removeXsqlBuilderOrders(String string) {
        Assert.hasText(string);
        Pattern p = Pattern.compile("/~.*order\\s*by[\\w|\\W|\\s|\\S]*~/", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(string);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            m.appendReplacement(sb, "");
        }
        m.appendTail(sb);
        return removeOrders(sb.toString());
	}
	

	/**
	 * 由queryRequest生成order by 子句
	 * @param queryRequest
	 * @param withOrderBy 是否增加"order by "前缀
	 * @return
	 */
	public static String buildOrderCaluse(QueryRequest queryRequest,boolean withOrderBy){
		StringBuilder sb = new StringBuilder();
		List<OrderBy> orders = queryRequest.orders();
		if(orders!=null && orders.size()>0){
			sb.append(withOrderBy ? " order by " : "");
			for(OrderBy order : orders){
				sb.append(order.field()).append(order.order()==Direction.DESC?" desc " : "").append(",");
			}
			sb.deleteCharAt(sb.length()-1);
		}
		return sb.toString();
	}
	/**
	 * 由pageRequest生成order by 子句
	 * @param pageRequest
	 * @return
	 */
	public static String buildOrderCaluse(QueryRequest  queryRequest){
		return buildOrderCaluse(queryRequest,true);
	}
	
	/**
	 * Return the conjuction of multiple expressions
	 *
	 * @param predicates The predicates making up the initial junction
	 *
	 * @return The conjunction
	 */
	public static Conjunction andCriterion(Criterion... predicates) {
		Conjunction conjunction = Restrictions.conjunction();
		if ( predicates != null ) {
			for ( Criterion predicate : predicates ) {
				conjunction.add( predicate );
			}
		}
		return conjunction;
	}
	
	public static XsqlFilterResult buildXsqlFilterResult(XsqlBuilder xsqlBuilder,String hql,QueryRequest queryRequest){
		Map<String,String> otherFilters = new HashMap<String,String>(1);
		otherFilters.put(SORT_COLUMNS_KEY, XSqlUtils.buildOrderCaluse(queryRequest, false));
		
		Map<String,Object> filters = XSqlUtils.params2Filter(queryRequest);
		// 混合使用otherFilters与pageRequest.getFilters()为一个filters使用
		filters.putAll(otherFilters);
		
		return xsqlBuilder.generateHql(hql,filters);		
	}
	
	/**
	 * Return the disjuction of multiple expressions
	 *
	 * @param predicates The predicates making up the initial junction
	 *
	 * @return The conjunction
	 */
	public static Disjunction orCriterion(Criterion... predicates) {
		Disjunction disjunction = Restrictions.disjunction();
		if ( predicates != null ) {
			for ( Criterion predicate : predicates ) {
				disjunction.add( predicate );
			}
		}
		return disjunction;
	}
	/**
	 * 将QueryRequest中的参数和值转换为map的形式,此时假定所有的参数都是BaseQueryParam类型的(只需要参数中的field和value)
	 * @param queryRequest
	 * @return
	 */
	public static Map<String,Object> params2Filter(QueryRequest queryRequest){
		Map<String,Object> map = new HashMap<String, Object>();
		for(QueryParam param : queryRequest.params()){
			if(param instanceof BaseQueryParam){
				map.put(((BaseQueryParam) param).field(), ((BaseQueryParam) param).value());
			}
		}
		return map;
	}

}
